home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / tcpint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  7.3 KB  |  362 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: tcpint.c,v 5.1 1992/11/01 00:01:21 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <sys/time.h>
  12. #include <syslog.h>
  13. #include <signal.h>
  14. #include <errno.h>
  15.  
  16. #include "access.h"
  17. #include "defs.h"
  18. #include "int.h"
  19. #include "config.h"
  20.  
  21. char *inet_ntoa() ;
  22. void msg() ;
  23.  
  24. typedef enum { S_OK, S_SERVER_ERR, S_CLIENT_ERR } stream_status_e ;
  25.  
  26. struct istream_private
  27. {
  28.     unsigned accepted_connections ;
  29. } ;
  30.  
  31. #define SIP( p )                        ((struct istream_private *)(p))
  32.  
  33. static struct istream_private istream ;
  34.  
  35. void si_mux() ;
  36. void si_exit() ;
  37.  
  38. static struct intercept_ops istream_ops =
  39.     {
  40.         si_mux,
  41.         si_exit
  42.     } ;
  43.  
  44. static struct intercept stream_intercept_state ;
  45.  
  46.  
  47. struct intercept *si_init( serp )
  48.     struct server *serp ;
  49. {
  50.     register struct intercept *ip = &stream_intercept_state ;
  51.  
  52.     ip->socket_type = SOCK_STREAM ;
  53.     ip->priv = &istream ;
  54.     ip->ops = &istream_ops ;
  55.     int_init( ip, serp ) ;
  56.     if ( (int) signal( SIGPIPE, SIG_IGN ) == -1 )
  57.         int_fail( ip, "signal" ) ;
  58.     return( ip ) ;
  59. }
  60.  
  61.  
  62. PRIVATE void si_exit()
  63. {
  64.     register struct intercept *ip = &stream_intercept_state ;
  65.     
  66.     if ( SIP( ip->priv )->accepted_connections == 0 )
  67.         (void) accept( INT_REMOTE( ip ), SA( NULL ), INT_NULL ) ;
  68.     int_exit( ip ) ;
  69. }
  70.  
  71.  
  72. PRIVATE void si_mux()
  73. {
  74.     register struct intercept *ip = &stream_intercept_state ;
  75.     fd_set socket_mask ;
  76.     int mask_max ;
  77.     psi_h iter ;
  78.     char *func = "si_mux" ;
  79.     status_e handle_io() ;
  80.     stream_status_e tcp_local_to_remote() ;
  81.     stream_status_e tcp_remote_to_local() ;
  82.     void connection_request() ;
  83.  
  84.     FD_ZERO( &socket_mask ) ;
  85.     FD_SET( INT_REMOTE( ip ), &socket_mask ) ;
  86.     mask_max = INT_REMOTE( ip ) ;
  87.  
  88.     iter = psi_create( INT_CONNECTIONS( ip ) ) ;
  89.     if ( iter == NULL )
  90.     {
  91.         msg( LOG_ERR, func, ES_NOMEM ) ;
  92.         return ;
  93.     }
  94.  
  95.     for ( ;; )
  96.     {
  97.         channel_s *chp ;
  98.         fd_set read_mask ;
  99.         int n_ready ;
  100.  
  101.         read_mask = socket_mask ;
  102.         n_ready = int_select( mask_max+1, &read_mask ) ;
  103.  
  104.         if ( n_ready == -1 )
  105.             return ;
  106.         
  107.       if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) )
  108.       {
  109.          connection_request( ip, &chp ) ;
  110.             if ( chp != NULL )
  111.             {
  112.                 FD_SET( chp->local_socket, &socket_mask ) ;
  113.                 if ( chp->local_socket > mask_max )
  114.                     mask_max = chp->local_socket ;
  115.                 FD_SET( chp->remote_socket, &socket_mask ) ;
  116.                 if ( chp->remote_socket > mask_max )
  117.                     mask_max = chp->remote_socket ;
  118.             }
  119.          if ( --n_ready == 0 )
  120.             continue ;
  121.       }
  122.  
  123.         for ( chp = CHP( psi_start(iter) ) ; chp ; chp = CHP( psi_next(iter) ) )
  124.         {
  125.             if ( FD_ISSET( chp->local_socket, &read_mask ) )
  126.             {
  127. #ifdef DEBUG_TCPINT
  128.                 if ( debug.on )
  129.                     msg( LOG_DEBUG, func, "Input available on local socket %d", 
  130.                                                                             chp->local_socket ) ;
  131. #endif
  132.                 if ( handle_io( ip, iter, chp,
  133.                                 &socket_mask, tcp_local_to_remote ) == FAILED )
  134.                     return ;
  135.                 if ( --n_ready == 0 )
  136.                     break ;
  137.             }
  138.  
  139.             if ( FD_ISSET( chp->remote_socket, &read_mask ) )
  140.             {
  141. #ifdef DEBUG_TCPINT
  142.                 msg( LOG_DEBUG, func, "Input available on remote socket %d", 
  143.                                                                         chp->remote_socket ) ;
  144. #endif
  145.                 if ( handle_io( ip, iter, chp,
  146.                                 &socket_mask, tcp_remote_to_local ) == FAILED )
  147.                     return ;
  148.                 if ( --n_ready == 0 )
  149.                     break ;
  150.             }
  151.         }
  152.     }
  153. }
  154.  
  155.  
  156. PRIVATE status_e handle_io( ip, iter, chp, maskp, iofunc )
  157.     struct intercept *ip ;
  158.     psi_h iter ;
  159.     channel_s *chp ;
  160.     fd_set *maskp ;
  161.     stream_status_e (*iofunc)() ;
  162. {
  163.     char *func = "handle_io" ;
  164.  
  165.     switch ( (*iofunc)( chp ) )
  166.     {
  167.         case S_SERVER_ERR:
  168.             return( FAILED ) ;
  169.         
  170.         case S_CLIENT_ERR:
  171.  
  172.             if ( debug.on )
  173.                 msg( LOG_DEBUG, func,
  174.                     "Closing channel to %s,%d using sockets %d(l),%d(r)",
  175.                         inet_ntoa( chp->from.sin_addr ), ntohs( chp->from.sin_port ),
  176.                         chp->local_socket, chp->remote_socket ) ;
  177.  
  178.             FD_CLR( chp->local_socket, maskp ) ;
  179.             FD_CLR( chp->remote_socket, maskp ) ;
  180.             (void) close( chp->remote_socket ) ;
  181.             (void) close( chp->local_socket ) ;
  182.             psi_remove( iter ) ;
  183.             fsm_free( INT_ALLOCATOR( ip ), (char *)chp ) ;
  184.             break ;
  185.     }
  186.     return( OK ) ;
  187. }
  188.  
  189.  
  190. PRIVATE void connection_request( ip, chpp )
  191.     struct intercept *ip ;
  192.     channel_s **chpp ;
  193. {
  194.     struct sockaddr_in sin ;
  195.     int sin_len = sizeof( sin ) ;
  196.     channel_s *chp ;
  197.     int sd ;
  198.     bool_int addr_checked ;
  199.     char *func = "connection_request" ;
  200.     void log_failure() ;
  201.     void log_success() ;
  202.  
  203.     *chpp = NULL ;
  204.  
  205.     if ( ( sd = accept( INT_REMOTE( ip ), SA( &sin ), &sin_len ) ) == -1 )
  206.         return ;
  207.     
  208.     SIP( ip->priv )->accepted_connections++ ;
  209.  
  210.     if ( debug.on )
  211.         msg( LOG_DEBUG, func, "connection request from %s,%d",
  212.             inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ) ) ;
  213.  
  214.     chp = int_lookupconn( ip, &sin, &addr_checked ) ;
  215.     if ( chp == NULL )
  216.     {
  217.         struct server *serp = INT_SERVER( ip ) ;
  218.         connection_s *cop = SERVER_CONNECTION( serp ) ;
  219.  
  220.         conn_fill( cop, &sin ) ;
  221.  
  222.         if ( INTERCEPT( ip ) )
  223.         {
  224.             mask_t check_mask ;
  225.             access_e result ;
  226.             struct service *sp = SERVER_SERVICE( serp ) ;
  227.             
  228.             M_OR( check_mask, MASK( CF_ADDRESS ), MASK( CF_TIME ) ) ;
  229.             result = access_control( sp, cop, &check_mask ) ;
  230.  
  231.             if ( result != AC_OK )
  232.             {
  233.                 log_failure( result, sp, cop ) ;
  234.                 (void) close( sd ) ;
  235.                 return ;
  236.             }
  237.         }
  238.  
  239.         if ( ( chp = int_newconn( ip, &sin, sd ) ) == NULL )
  240.         {
  241.             (void) close( sd ) ;
  242.             return ;
  243.         }
  244.         
  245.         if ( ! addr_checked )
  246.             log_success( serp ) ;
  247.         
  248.         *chpp = chp ;
  249.     }
  250.     else
  251.         msg( LOG_ERR, func,
  252.             "Received another connection request from %s,%d",
  253.                 inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ) ) ;
  254. }
  255.  
  256.  
  257. PRIVATE stream_status_e tcp_local_to_remote( chp )
  258.     channel_s *chp ;
  259. {
  260.     char buf[ DATAGRAM_SIZE ] ;
  261.     int rcc, wcc ;
  262.     char *p ;
  263.     int left ;
  264.     char *func = "tcp_local_to_remote" ;
  265.  
  266.     for ( ;; )
  267.     {
  268.         rcc = recv( chp->local_socket, buf, sizeof( buf ), 0 ) ;
  269.         if ( rcc == 0 )
  270.             return( S_SERVER_ERR ) ;
  271.         else if ( rcc == -1 )
  272.         {
  273.             if ( errno != EINTR )
  274.             {
  275.                 msg( LOG_ERR, func, "recv: %m" ) ;
  276.                 return( S_SERVER_ERR ) ;
  277.             }
  278.         }
  279.         else
  280.             break ;
  281.     }
  282.  
  283.     for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc )
  284.     {
  285.         wcc = send( chp->remote_socket, p, left, 0 ) ;
  286.         if ( wcc == 0 )
  287.             return( S_CLIENT_ERR ) ;
  288.         else if ( wcc == -1 )
  289.         {
  290.             if ( errno == EINTR )
  291.                 wcc = 0 ;
  292.             else
  293.             {
  294.                 msg( LOG_ERR, func, "send: %m" ) ;
  295.                 return( S_CLIENT_ERR ) ;
  296.             }
  297.         }
  298.     }
  299.  
  300. #ifdef DEBUG_TCPINT
  301.     if ( debug.on )
  302.         msg( LOG_DEBUG, func,
  303.             "Transferred %d bytes from local socket %d to remote socket %d",
  304.                 rcc, chp->local_socket, chp->remote_socket ) ;
  305. #endif
  306.  
  307.     return( S_OK ) ;
  308. }
  309.  
  310.  
  311. PRIVATE stream_status_e tcp_remote_to_local( chp )
  312.     channel_s *chp ;
  313. {
  314.     char buf[ DATAGRAM_SIZE ] ;
  315.     int rcc, wcc ;
  316.     int left ;
  317.     char *p ;
  318.     char *func = "tcp_remote_to_local" ;
  319.  
  320.     for ( ;; )
  321.     {
  322.         rcc = recv( chp->remote_socket, buf, sizeof( buf ), 0 ) ;
  323.         if ( rcc == 0 )
  324.             return( S_CLIENT_ERR ) ;
  325.         else if ( rcc == -1 )
  326.         {
  327.             if ( errno != EINTR )
  328.             {
  329.                 msg( LOG_ERR, func, "recv: %m" ) ;
  330.                 return( S_CLIENT_ERR ) ;
  331.             }
  332.         }
  333.         else
  334.             break ;
  335.     }
  336.  
  337.     for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc )
  338.     {
  339.         wcc = send( chp->local_socket, p, left, 0 ) ;
  340.         if ( wcc == 0 )
  341.             return( S_SERVER_ERR ) ;
  342.         else if ( wcc == -1 )
  343.             if ( errno == EINTR )
  344.                 rcc = 0 ;
  345.             else
  346.             {
  347.                 msg( LOG_ERR, func, "send: %m" ) ;
  348.                 return( S_SERVER_ERR ) ;
  349.             }
  350.     }
  351.  
  352. #ifdef DEBUG_TCPINT
  353.     if ( debug.on )
  354.         msg( LOG_DEBUG, func,
  355.             "Transferred %d bytes from remote socket %d to local socket %d",
  356.                 rcc, chp->remote_socket, chp->local_socket ) ;
  357. #endif
  358.  
  359.     return( S_OK ) ;
  360. }
  361.  
  362.